from django.db.models import *
from django.core.files.images import ImageFile
from os import path
import re, tempfile
from warnings import warn



class XMLFile(Model):
    """\
    This class represents a file in the original ftb bundle.
    It stores only the file name. For performances reasons, the file content is stored in XMLContent.
    """
    name = CharField(max_length=100, unique=True)
    def __unicode__(self):
        return self.name

    def number_of_sentences(self):
        return self.sentence_set.count()
    
class XMLContent(Model):
    """\
    This is the class that stores xml file contents.
    """
    content = XMLField(schema_path=path.join(settings.ROOT, "core", "Paris7treebank.rng"))
    file = OneToOneField('XMLFile')    


class Sentence(Model):
    """\
    This is the base class : represents a sentence.
    """
    nb = CharField(max_length=10)
    xml =  XMLField(schema_path=path.join(settings.ROOT, "core", "Paris7treebank.rng"))
    file = ForeignKey('XMLFile')
    
    tree = ForeignKey('TreeNode')
    tree_image = ImageField(upload_to="trees", blank=True)

    def image(self):
        if not self.tree_image:
            try:
                from graphs import TreeNode2Digraph
                tempname = tempfile.mktemp(".png", "tree_", path.join(settings.ROOT, "static/tmp"))
                g = TreeNode2Digraph(self.tree)
                g.layout(yapgvb.engines.dot)
                g.render(tempname)
                image_file = ImageFile(open(tempname, 'rw'))
                self.tree_image = image_file
                self.save()
            except ImportError:
                warn("Can't import graph library", ImportWarning)
                return None
        return self.tree_image


    def __unicode__(self):
        """\
        return the file and index as description
        """
        return u"Sentence %s of file %s" % (self.nb, self.file.name)

    @permalink
    def get_absolute_url(self):
        return ('ftbexplorer.core.views.sentence', (), {
                'filename':self.file.name,
                'nb':self.nb})


    def words(self):
        return self.word_set.order_by("index")

    def text(self):
        if hasattr(self, '_text'):
            return self._text
        else:
            words = self.word_set.order_by("index")
            words = map(lambda x: x.form, words)
            self._text = u" ".join(words)
            self._text = re.sub(r'([-\'\(])\s+', r'\1', self._text)
            self._text = re.sub(r'\s+([-.,\'\)])', r'\1', self._text)
            return self._text
        

class Word(Model):
    index = IntegerField()
    sentence = ForeignKey('Sentence')
    form = CharField(max_length=1024)
    lemma = CharField(max_length=1024)
    cat = CharField(max_length=128)
    ee = CharField(max_length=128)
    ei = CharField(max_length=128)
    mph = CharField(max_length=128)
    subcat = CharField(max_length=128)
    

    
    def __unicode__(self):
        return self.form
    

class TreeNode(Model):
    sibling_index = IntegerField()
    nodeName =  CharField(max_length=128) 
    data = CharField(max_length=1024, blank=True)
    function = CharField(max_length=128, blank=True)
    parent = ForeignKey('TreeNode', blank=True, null=True)

    def children(self):
        return self.treenode_set.order_by("sibling_index")
        
    def getattr(self, key, default=None):
        try:
            return self.nodeattribute_set.get(node=self, key=key).value
        except NodeAttribute.DoesNotExist:
            return default
    
    def setattr(self, key, value):
        try:
            attr = NodeAttribute.objects.get(node=self, key=key)
            attr.value = value
            attr.save()
        except NodeAttribute.DoesNotExist:
            attr = NodeAttribute(node=self, key=key, value=value)
            attr.save()
    
    def __unicode__(self):
        if self.nodeName == "#text":
            return self.data
        else:
            return self.nodeName
    
    def graph(self):
        try:
            import yapgvb
        except ImportError:
            return None
        g = yapgvb.Digraph('syntactic_tree')
        def add_node(tree_node):
            label = unicode(tree_node).encode("utf8")
            if label == "w":
                if tree_node.getattr("cat"):
                    label = tree_node.getattr("cat").encode("utf8")
            label = label.encode("utf-8")
            node = g.add_node(None,
                label = label,
                style = "filled",
                color = NODE_COLORS.get(tree_node.nodeName, 'gray'))
            for a_child in tree_node.children():
                child_node = add_node(a_child)
                node >> child_node
            return node
        add_node(self)
        return g

class NodeAttribute(Model):
    node = ForeignKey('TreeNode')
    key = CharField(max_length=255)
    value = CharField(max_length=255)

